﻿using Guwave.MonitorDevice.Common;
using Guwave.MonitorDevice.WPFClientApp.Model;
using Guwave.MonitorDevice.WPFClientApp.Views;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using System.Xml;
using System.Windows.Forms;
using System.IO.Ports;
using System.Drawing;
using MessageBox = System.Windows.MessageBox;
using OpenFileDialog = Microsoft.Win32.OpenFileDialog;
using TreeViewItem = System.Windows.Controls.TreeViewItem;
using Timer = System.Threading.Timer;
using Guwave.MonitorDevice.Utility;
using System.Threading;
using Guwave.MonitorDevice.WPFApp.Model.Request;
using Guwave.MonitorDevice.WPFApp.Model.Response;
using Guwave.MonitorDevice.Interface;
using Guwave.MonitorDevice.Service;
using Unity;
using Guwave.MonitorDevice.Interface.Entity;
using Guwave.MonitorDevice.WPFClientApp.Utility;
using log4net.Config;
using log4net;
using System.IO;

namespace Guwave.MonitorDevice.WPFClientApp.ViewModel
{
    public class MonitorDeviceViewModel : INotifyPropertyChanged
    {
        //实例化容器
        private IUnityContainer _container = new UnityContainer();
        private Timer _timerDevice;
        private Timer _timerFile;
        private NotifyIcon _notifyIcon = new NotifyIcon();
        private ContextMenuStrip _cms = new ContextMenuStrip();
        private ToolStripMenuItem _tsmiSetting = new ToolStripMenuItem();
        private ToolStripMenuItem _tsmiStartAndCloseReadDevice = new ToolStripMenuItem();
        private ToolStripMenuItem _tsmiQuit = new ToolStripMenuItem();
        private ToolStripMenuItem _tsmiStartAndCloseReadFile = new ToolStripMenuItem();
        private SerialPort _serialPort = new SerialPort();

        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

        #region 数据属性
        public MonitorDeviceModel MonitorDeviceModel { get; set; } = new MonitorDeviceModel();

        private ObservableCollection<Visibility> _groupBoxVisibilities;
        public ObservableCollection<Visibility> GroupBoxVisibilities
        {
            get { return _groupBoxVisibilities; }
            set
            {
                _groupBoxVisibilities = value;
                OnPropertyChanged(nameof(GroupBoxVisibilities));
            }
        }

        private int _firstRowHeight;
        public int FirstRowHeight
        {
            get { return _firstRowHeight; }
            set
            {
                _firstRowHeight = value;
                OnPropertyChanged(nameof(FirstRowHeight));
            }
        }

        private int _twoRowHeight;
        public int TwoRowHeight
        {
            get { return _twoRowHeight; }
            set
            {
                _twoRowHeight = value;
                OnPropertyChanged(nameof(TwoRowHeight));
            }
        }

        /// <summary>
        /// 窗体大小
        /// </summary>
        private WindowState _windowState;
        public WindowState WindowState
        {
            get { return _windowState; }
            set
            {
                _windowState = value;
                OnPropertyChanged(nameof(WindowState));
            }
        }

        /// <summary>
        /// 窗体显示/隐藏
        /// </summary>
        public Visibility _windowVisibility;
        public Visibility WindowVisibility
        {
            get { return _windowVisibility; }
            set
            {
                _windowVisibility = value;
                OnPropertyChanged(nameof(WindowVisibility));
            }
        }
        #endregion

        #region 命令属性
        /// <summary>
        /// 取消配置命令
        /// </summary>
        public CommandBase CancelCommand { get; set; }

        /// <summary>
        /// 确认命令
        /// </summary>
        public CommandBase OkCommand { get; set; }

        /// <summary>
        /// 选择文件命令
        /// </summary>
        public CommandBase ChooseFileCommand { get; set; }

        /// <summary>
        /// 窗体大小改变命令
        /// </summary>
        public CommandBase WindowStateChangedCommand { get; set; }

        /// <summary>
        /// TreeView选中项改变命令
        /// </summary>
        public CommandBase TreeviewSelectedItemChangedCommand { get; set; }

        /// <summary>
        /// 窗体关闭命令
        /// </summary>
        public CommandBase ColsingCommand { get; set; }

        #endregion

        /// <summary>
        ///  Ctor
        /// </summary>
        public MonitorDeviceViewModel()
        {
            WindowVisibility = Visibility.Collapsed;
            WindowState = WindowState.Minimized;
            //注册类型
            _container.RegisterType<IMonitorDevicesService, MonitorDevicesService>();
            XmlConfigurator.Configure(new FileInfo(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Config\\log4Net.config")));
            GroupBoxVisibilities = new ObservableCollection<Visibility>()
            {
                Visibility.Visible,
                Visibility.Collapsed,
                Visibility.Collapsed
            };
            FirstRowHeight = 70;
            //窗体大小改变命令
            this.WindowStateChangedCommand = new CommandBase()
            {
                DoExecute = WindowStateChanged,
                DoCanExecute = o => { return true; }
            };
            //TreeView选中项改变命令
            this.TreeviewSelectedItemChangedCommand = new CommandBase()
            {
                DoExecute = ControlGroupBoxVisibility,
                DoCanExecute = o => { return true; }
            };
            //选择文件命令
            this.ChooseFileCommand = new CommandBase()
            {
                DoExecute = ChooseFile,
                DoCanExecute = o => { return true; }
            };
            //取消配置命令
            this.CancelCommand = new CommandBase()
            {
                DoExecute = obj => { WindowState = WindowState.Minimized; },
                DoCanExecute = o => { return true; }
            };
            //确认配置命令
            this.OkCommand = new CommandBase()
            {
                DoExecute = SaveConfig,
                DoCanExecute = o => { return true; }
            };
            //窗体关闭命令
            this.ColsingCommand = new CommandBase()
            {
                DoExecute = obj =>
                {
                    var eventArg = (System.ComponentModel.CancelEventArgs)obj;
                    eventArg.Cancel = true;
                    WindowState = WindowState.Minimized;
                },
                DoCanExecute = o => { return true; }
            };
            LoadConfig();//加载配置
            InitializeNotifyIcon();//初始化托盘
        }

        /// <summary>
        /// 控制GroupBox显示/隐藏
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ControlGroupBoxVisibility(object obj)
        {
            var tvItem = (TreeViewItem)obj;
            if (tvItem.Name == "SetInfanceAddressNode")
            {
                GroupBoxVisibilities[0] = Visibility.Visible;
                GroupBoxVisibilities[1] = Visibility.Collapsed;
                GroupBoxVisibilities[2] = Visibility.Collapsed;
                FirstRowHeight = 70;
            }
            else if (tvItem.Name == "SetReadDriveParameterNode")
            {
                GroupBoxVisibilities[1] = Visibility.Visible;
                GroupBoxVisibilities[0] = Visibility.Collapsed;
                GroupBoxVisibilities[2] = Visibility.Collapsed;
                FirstRowHeight = 0;
                TwoRowHeight = 120;
            }
            else if (tvItem.Name == "SetReadFileNode")
            {
                GroupBoxVisibilities[2] = Visibility.Visible;
                GroupBoxVisibilities[0] = Visibility.Collapsed;
                GroupBoxVisibilities[1] = Visibility.Collapsed;
                FirstRowHeight = 0;
                TwoRowHeight = 0;
            }
        }

        /// <summary>
        /// 窗体大小改变
        /// </summary>
        /// <param name="obj"></param>
        private void WindowStateChanged(object obj)
        {
            if (WindowState == WindowState.Minimized)
            {
                WindowVisibility = Visibility.Collapsed;
                //托盘区图标Visible
                _notifyIcon.Visible = true;
            }
            else if (WindowState == WindowState.Maximized)
            {
                WindowState = WindowState.Normal;
                _notifyIcon.Visible = false;
            }
            else
            {
                _notifyIcon.Visible = false;
            }
        }

        /// <summary>
        /// 托盘单击设置
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void SettingHandler(object sender, EventArgs e)
        {
            if (WindowState == WindowState.Minimized)
            {
                //窗体显示
                WindowVisibility = Visibility.Visible;
                //还原窗体
                WindowState = WindowState.Maximized;
                //托盘区图标隐藏
                _notifyIcon.Visible = false;
            }
        }

        /// <summary>
        /// 加载配置
        /// </summary>
        private void LoadConfig()
        {
            GetConfigValue(ConfigInfo.InfanceArrdess);//加载接口地址
            GetConfigValue(ConfigInfo.DeviceIntervalTime);//加载读取设备间隔时间
            GetConfigValue(ConfigInfo.DevicesInfo, "Points");//加载端口
            GetConfigValue(ConfigInfo.DevicesInfo, "ReadBuffers");//加载波特率
            GetConfigValue(ConfigInfo.FileIntervalTime);//加载读取文件间隔时间 & 文件路径
        }

        /// <summary>
        /// 初始化托盘
        /// </summary>
        private void InitializeNotifyIcon()
        {
            // notifyIcon
            this._notifyIcon.ContextMenuStrip = this._cms;
            this._notifyIcon.Icon = Properties.Resources.favicon;
            this._notifyIcon.Text = "我的托盘";
            this._notifyIcon.Visible = true;
            // contextMenuStrip
            this._cms.ImageScalingSize = new System.Drawing.Size(24, 24);
            this._cms.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
            this._tsmiSetting,
            this._tsmiStartAndCloseReadDevice,
            this._tsmiStartAndCloseReadFile,
            this._tsmiQuit});
            this._cms.Name = "contextMenuStrip1";
            this._cms.Size = new System.Drawing.Size(149, 70);
            // cmpSetting
            this._tsmiSetting.Name = "cmpSetting";
            this._tsmiSetting.Size = new System.Drawing.Size(148, 22);
            this._tsmiSetting.Text = "设置";
            this._tsmiSetting.Click += new EventHandler(this.SettingHandler);
            // cmpStartReadDevice
            this._tsmiStartAndCloseReadDevice.Name = "cmpStartReadDevice";
            this._tsmiStartAndCloseReadDevice.Size = new System.Drawing.Size(148, 22);
            this._tsmiStartAndCloseReadDevice.Text = "开始读取设备";
            this._tsmiStartAndCloseReadDevice.ToolTipText = "已停止";
            this._tsmiStartAndCloseReadDevice.Click += new EventHandler(this.StartAndCloseReadDeviceHandler);
            // cmpStartReadFile
            this._tsmiStartAndCloseReadFile.Name = "cmpStartReadFile";
            this._tsmiStartAndCloseReadFile.Size = new System.Drawing.Size(148, 22);
            this._tsmiStartAndCloseReadFile.Text = "开始读取文件";
            this._tsmiStartAndCloseReadFile.ToolTipText = "已停止";
            this._tsmiStartAndCloseReadFile.Click += new EventHandler(this.StartAndCloseReadFileHandler);
            // quit
            this._tsmiQuit.Name = "quit";
            this._tsmiQuit.Size = new System.Drawing.Size(148, 22);
            this._tsmiQuit.Text = "退出";
            this._tsmiQuit.Click += new System.EventHandler(this.QuitHandler);
        }

        /// <summary>
        /// 选择ini文件
        /// </summary>
        private void ChooseFile(object obj)
        {
            OpenFileDialog dialog = new OpenFileDialog();
            dialog.Multiselect = false;
            dialog.Title = "请选择文件";
            dialog.Filter = "ini文件(*ini*)|*ini*";
            if (dialog.ShowDialog() == true)
            {
                MonitorDeviceModel.FilePath = dialog.FileName;
            }
        }

        /// <summary>
        /// 托盘退出事件处理函数
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void QuitHandler(object sender, EventArgs e)
        {
            System.Windows.Application.Current.Shutdown();
        }

        /// <summary>
        /// 托盘开始/关闭读取设备事件处理函数
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void StartAndCloseReadDeviceHandler(object sender, EventArgs e)
        {
            StartAndCloseReadDevice();//开始读取/关闭设备
        }

        /// <summary>
        /// 开始读取/关闭设备
        /// </summary>
        private void StartAndCloseReadDevice()
        {
            if (this._timerDevice != null)
            {
                _timerDevice.Dispose();
                _timerDevice = null;
                this._tsmiStartAndCloseReadDevice.Text = "开始读取设备";
                this._tsmiStartAndCloseReadDevice.ToolTipText = "已停止";
            }
            else
            {
                TimerCallback deviceTimerCallback = new TimerCallback(ReadDeviceInfo);
                _timerDevice = new System.Threading.Timer(deviceTimerCallback, "读取设备", 0, Convert.ToInt32(this.MonitorDeviceModel.ReadDeviceIntervalTime));
                this._tsmiStartAndCloseReadDevice.Text = "关闭读取设备";
                this._tsmiStartAndCloseReadDevice.ToolTipText = "正在运行";
            }
        }

        /// <summary>
        /// 读取设备的一些信息
        /// </summary>
        private void ReadDeviceInfo(object state)
        {
            IMonitorDevicesService iMonitorDevicesService = _container.Resolve<MonitorDevicesService>();
            MonitorDeviceEntity monitorDeviceEntity = iMonitorDevicesService.GetDeviceAllInfo();
            string requestJson = JsonHelper.ModelToJson(monitorDeviceEntity);
            //访问远程接口
            CallRemoteInterface(requestJson);
        }

        /// <summary>
        /// 托盘开始/关闭读取文件事件处理函数
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void StartAndCloseReadFileHandler(object sender, EventArgs e)
        {
            StartAndCloseReadFile();//开始/关闭读取文件
        }

        /// <summary>
        /// 开始/关闭读取文件
        /// </summary>
        private void StartAndCloseReadFile()
        {
            if (this._timerFile != null)
            {
                this._timerFile.Dispose();
                this._timerFile = null;
                this._tsmiStartAndCloseReadFile.Text = "开始读取文件";
                this._tsmiStartAndCloseReadFile.ToolTipText = "已停止";
            }
            else
            {
                if (this.MonitorDeviceModel.FilePath.IsEmpty())
                {
                    MessageBox.Show("文件路径不能为空", "提示");
                    return;
                }
                TimerCallback fileCallback = new TimerCallback(ReadINIFileInfo);
                _timerFile = new System.Threading.Timer(fileCallback, "读取ini文件", 0, Convert.ToInt32(this.MonitorDeviceModel.ReadFileIntervalTime));
                this._tsmiStartAndCloseReadFile.Text = "关闭读取文件";
                this._tsmiStartAndCloseReadFile.ToolTipText = "正在运行";
            }
        }

        /// <summary>
        /// 读取文件信息
        /// </summary>
        /// <param name="state"></param>
        private void ReadINIFileInfo(object state)
        {
            INIFile iniFile = new INIFile(this.MonitorDeviceModel.FilePath);
            string eqpId = iniFile.IniReadValue("config", "eqpId");
            string runStatus = iniFile.IniReadValue("config", "runStatus");
            string commStatus = iniFile.IniReadValue("config", "commStatus");
            string task = iniFile.IniReadValue("config", "task");

            ReqDrivcesInfo reqDrivcesInfo = new ReqDrivcesInfo()
            {
                eqpId = eqpId,
                runStatus = runStatus.ToStringOrNull(),
                commStatus = commStatus.ToStringOrNull(),
                task = task
            };
            string requestJson = JsonHelper.ModelToJson(reqDrivcesInfo);
            //访问远程接口
            CallRemoteInterface(requestJson);
        }

        /// <summary>
        /// 访问远程接口
        /// </summary>
        /// <param name="content"></param>
        private void CallRemoteInterface(string content)
        {
            string respStr = HttpHelper.SendDataByPut(this.MonitorDeviceModel.InfanceArrdess, content, "application/json", "application/json");
            if (!respStr.IsEmpty())
            {
                RespResult respResult = JsonHelper.JsonToModel<RespResult>(respStr);
                if (respResult.code != 200)//只记录错误日志
                {
                    ILog ilog = LogManager.GetLogger(typeof(MonitorDeviceView));
                    ilog.Error(respResult.code + "-" + respResult.msg + "-body:" + content);
                }
            }
        }

        /// <summary>
        /// 保存配置
        /// </summary>
        /// <param name="obj"></param>
        private void SaveConfig(object obj)
        {
            ConfigManager config = new ConfigManager(MonitorDeviceModel, GroupBoxVisibilities);
            config.SaveConfig();
            WindowState = WindowState.Minimized;
        }

        /// <summary>
        /// 得到配置的值
        /// </summary>
        /// <param name="configInfoEnum"></param>
        /// <param name="attributeName"></param>
        private void GetConfigValue(ConfigInfo configInfoEnum, string attributeName = "")
        {
            ConfigManager config = new ConfigManager(MonitorDeviceModel, GroupBoxVisibilities);
            config.GetConfigValue(configInfoEnum, attributeName);
        }
    }
}
